#pragma once
#include <Winsock2.h>
#include  <list>

#ifdef REMJOBNET_EXPORTS
   #define DLLDIR  __declspec(dllexport)   
   #define EXPORT_TEMPL
#else
   #define DLLDIR  __declspec(dllimport)   
   #define EXPORT_TEMPL extern
#endif 

using namespace std;

//EXPORT_TEMPL template class DLLDIR list<u_short>;
//EXPORT_TEMPL template class DLLDIR allocator<u_short>;

namespace remjob{
	
	typedef enum command_t{
		DISCOVERY,
		HELLO,
		START,
		STOP,
		INSTALL,
		PFILE,
		FILEM,
		UNINSTALL,
		LOG,
		STATUS_REQ,
		STATUS_REP,		
	} Command;

	typedef list<u_short> GroupList;

	class DLLDIR Packet {
	private:

		Command type;
		u_short id_operation;
		u_int id_sender;

		GroupList id_groups;

	public:
		Packet ( Command type,
			u_short id_operation,
			u_int id_sender, 
			GroupList id_groups);

		Command getCommand();
		u_short getOperation();
		u_int getSender();
		GroupList getGroups();

		/*virtual*/ int serialize(char *buffer, int len);
		static Packet *read(char *buffer, int len);
		static void write_string(char *buffer, string result, u_short size, int len);
		static void read_string(char *buffer, string result, u_short size, int len);
	};

	class DLLDIR PFile: public Packet{

	private:
		u_short id_application;
		u_short size;
		string application;
		u_int len;
		u_short id_file_operation;
		char checksum[20];

	public:
		PFile(Command type,u_short id_operation,u_int id_sender, GroupList id_groups);
		/*static*/ Packet* read(char *buffer, int len);
		int serialize(char *buffer, int len);

		void setApplicationId(u_short id_application);
		void setApplicationName(string application, u_short size);
		void setLen(u_int len);
		void setFileOperationId(u_int id_file_operation);
		void setChecksum(char* checksum);

		u_short getApplicationId();
		u_short getDim();
		string getApplicationName();
		u_int getLen();
		u_int getFileOperationId();
		char *getChecksum();
	};

	class DLLDIR PApplication: Packet{
	private:
		u_short id_application;
		string application;

	public:

		PApplication(Command type,u_short id_operation,u_int id_sender, GroupList id_groups);
		/*static*/ Packet* read(char *buffer, int len);
		int serialize(char *buffer, int len);

		void setApplicationId(u_short id_application);
		void setApplicationName(string application);

		u_short getApplicationId();
		string getApplicationName();
	};

	class DLLDIR PFileTransfer: Packet{
	private:
		u_short id_application;
		u_int offset;
		char* buffer;
		int len;

	public:
		PFileTransfer(Command type, u_short id_operation, u_int id_sender, GroupList id_groups);
		/*static*/ Packet* read(char *buffer, int len);
		int serialize(char *buffer, int len);

		void setApplicationId(u_short id_application);
		void setOffset(u_int offset);
		void setBuffer(char *buffer, int len);

		u_short getApplicationId();
		u_int getOffset();
	};

	class DLLDIR PNack: Packet {
	private:
		u_int offset;
	public:
		PNack(Command type,u_short id_operation,u_int id_sender, GroupList id_groups);
		static Packet* read(char *buffer, int len);
		int serialize(char *buffer, int len);

		void setOffset(u_int offset);
		u_int getOffset();
	};
}
